package utils

import (
	"bytes"
	"fmt"
	"strings"
	"time"
)

const StatusRunning = "running"           //服务正在运行
const StatusDead = "dead"                 //服务未运行，已停止
const StatusWaiting = "waiting"           //务正在等待某些条件满足，尚未开始运行
const StatusExited = "exited"             //服务已成功启动并已退出
const StatusActivating = "activating"     // 服务正在启动中
const StatusDeactivating = "deactivating" // 服务正在停止中

func startSvc(service string) error {
	_, err := ExecCmd(".", []string{}, bytes.Buffer{}, "systemctl", "daemon-reload")
	if err != nil {
		return nil
	}
	_, err = ExecCmd(".", []string{}, bytes.Buffer{}, "systemctl", "start", service)
	if err != nil {
		return nil
	}
	_, err = ExecCmd(".", []string{}, bytes.Buffer{}, "systemctl", "enable", service)
	if err != nil {
		return nil
	}

	return nil
}

func restartSvc(service string) error {
	_, err := ExecCmd(".", []string{}, bytes.Buffer{}, "systemctl", "restart", service)
	if err != nil {
		return nil
	}

	return nil
}

func stopSvc(service string) error {
	return nil
}

func checkSvcStart(service string) error {
	status, err := ServiceStatus(service)
	if err != nil {
		return err
	}
	if status != StatusRunning {
		for i := 1; i <= 15; i++ {
			time.Sleep(2 * time.Second)
			status, err = ServiceStatus(service)
			if err != nil {
				return err
			}
			if status == StatusRunning {
				return nil
			}
		}
		return fmt.Errorf(status)
	}
	return nil
}

func ServiceStatus(service string) (string, error) {
	stdout, err := ExecCmdChains(".", []string{}, bytes.Buffer{}, []Command{
		{"systemctl", []string{"status", service}},
		{"grep", []string{"Active"}},
	})
	if err != nil {
		return "", err
	}

	var status string

	switch {
	case strings.Contains(stdout.String(), "running"):
		status = StatusRunning
	case strings.Contains(stdout.String(), "dead"):
		status = StatusDead
	case strings.Contains(stdout.String(), "waiting"):
		status = StatusWaiting
	case strings.Contains(stdout.String(), "exited"):
		status = StatusExited
	case strings.Contains(stdout.String(), "activating"):
		status = StatusActivating
	case strings.Contains(stdout.String(), "deactivating"):
		status = StatusDeactivating
	default:
		errString := fmt.Sprintf("%s has no status information", service)
		Logger.Error(errString)
		return "", fmt.Errorf(errString)
	}
	Logger.Debug(fmt.Sprintf("service %s status: %s", service, status))

	return status, nil

}

func RegisterService(service string) error {
	err := startSvc(service)
	if err != nil {
		return err
	}

	status, err := ServiceStatus(service)
	if err != nil {
		return err
	}
	if status != StatusRunning {
		for i := 1; i <= 5; i++ {
			time.Sleep(2 * time.Second)
			status, err = ServiceStatus(service)
			if err != nil {
				return err
			}
			if status == StatusRunning {
				return nil
			}
		}
		return fmt.Errorf(status)
	}
	return nil

}

func RestartService(service string) error {
	err := restartSvc(service)
	if err != nil {
		return err
	}

	err = checkSvcStart(service)
	if err != nil {
		return err
	}

	return nil
}
